﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ZeroBug.EasyFlow.Motion;

namespace Kimd.DMCEtherCard
{
    public class DMCEtherCardAxisOperator : IAxis
    {
        private bool _isErr;
        private string _lastError;
        public bool[] IsHomeFinish { get ; set; } = new bool[64];
        public bool IsError { get; set; }

        public string LastError { get; set; }

        public double AccUnitConvert(double vel, double acc)
        {
            return acc;
        }

        public bool GetAxisHomeFound(short cardNo, short axisNo)
        {
            ushort hmd = 0;
            csLTDMC.LTDMC.dmc_get_home_result((ushort)cardNo, (ushort)(axisNo - 1), ref hmd);
            bool result = (hmd == 1 ? true : false);
            return result;
        }
        public bool ClearOffset(short cardNo, short axisNo)
        {
            short rtn = csLTDMC.LTDMC.nmc_set_offset_pos((ushort)cardNo, (ushort)(axisNo - 1), 0);
            return CheckApiResult(rtn, $"轴清除绝对值编码器失败!");
        }
        public bool AxisGoHome(short cardNo, short axisNo, short homeMode, bool homeDir, AxisSpeed homeSpeed)
        {
            int rtn = 0;
            int dir = homeDir ? 1 : 0;//0 --反 1--正
            rtn += csLTDMC.LTDMC.nmc_set_home_profile((ushort)cardNo, (ushort)(axisNo - 1), (ushort)homeMode, homeSpeed.VelStart, homeSpeed.Vel, homeSpeed.Acc, homeSpeed.Dec, homeSpeed.VelEnd);
            rtn += csLTDMC.LTDMC.nmc_home_move((ushort)cardNo, (ushort)(axisNo - 1));  //设定遇极限反转
            return CheckApiResult((short)rtn, $"轴执行回原点运动失败!");
        }
        public bool AxisMoveAbsolute(short cardNo, short axisNo, int distanceInPulse, AxisSpeed axisSpeed)
        {
            short rtn = csLTDMC.LTDMC.dmc_set_profile_unit((ushort)cardNo, (ushort)(axisNo - 1), axisSpeed.VelStart, axisSpeed.Vel, axisSpeed.Acc, axisSpeed.Dec, axisSpeed.VelEnd);
            rtn += csLTDMC.LTDMC.dmc_set_s_profile((ushort)cardNo, (ushort)(axisNo - 1), 0, axisSpeed.STime);
            if (!CheckApiResult(rtn, "设置轴运动速度失败!"))
                return false;
            rtn += csLTDMC. LTDMC.dmc_pmove((ushort)cardNo, (ushort)(axisNo - 1), distanceInPulse, 1);
            return CheckApiResult(rtn, "设置轴点位运动失败!");
        }

        public bool AxisMoveContinous(short cardNo, short axisNo, MoveDirection direction, AxisSpeed axisSpeed)
        {
            short rtn = csLTDMC.LTDMC.dmc_set_profile_unit((ushort)cardNo, (ushort)(axisNo - 1), axisSpeed.VelStart, axisSpeed.Vel, axisSpeed.Acc, axisSpeed.Dec, axisSpeed.VelEnd);
            if (!CheckApiResult(rtn, "设置轴运动速度失败!"))
                return false;
            return CheckApiResult(csLTDMC.LTDMC.dmc_vmove((ushort)cardNo, (ushort)(axisNo - 1), (ushort)(direction == MoveDirection.Positive ? 1 : 0)), "设置轴连续运动失败!");
        }

        public bool AxisMoveRelative(short cardNo, short axisNo, int offsetInPulse, AxisSpeed axisSpeed)
        {
            throw new NotImplementedException();
        }

        public bool CheckApiResult(short rtn, string err)
        {
            if (rtn != 0)
            {
                //_isApiErr = true;
                //string errorStr = ErrorCode2ErrorStr(rtn);
                //MachineMessage.CallException(ExceptionType.FatalErr, "轴卡", $"[{rtn}{errorStr}]:{err}", MachineErrCode.CardErr);
                return false;
            }
            return true;
        }

        public void ClearAxisStatus(short cardNo, short axisNo)
        {

        }

        public double GetAxisCommandPosition(short cardNo, short axisNo)
        {
            double pos = 0;
            csLTDMC. LTDMC.dmc_get_position_unit((ushort)cardNo, (ushort)(axisNo - 1), ref pos);
            return pos;
        }

        public double GetAxisEncoderPosition(short cardNo, short axisNo)
        {
            double pos = 0;
            csLTDMC. LTDMC.dmc_get_encoder_unit((ushort)cardNo, (ushort)(axisNo - 1), ref pos);
            return pos;
        }

        public AxisStatus GetAxisStatus(short cardNo, short axisNo)
        {
            uint sts = csLTDMC.LTDMC.dmc_axis_io_status((ushort)cardNo, (ushort)(axisNo - 1));
            //0 为 true 1为false
            ushort Axis_StationMachine = 0;
            csLTDMC.LTDMC.nmc_get_axis_state_machine((ushort)cardNo, (ushort)(axisNo - 1), ref Axis_StationMachine);
            AxisStatus axisSts = new AxisStatus()
            {
                ServoWarn = (sts >> 0 & 0x01) == 1,
                ReachPosition = true,
                NegativeLimit = (sts >> 2 & 0x01) == 1,
                PositiveLimit = (sts >> 1 & 0x01) == 1,
                Origin = ((sts >> 4) & 0x01) == 1,
                EmergencyStop = ((sts >> 3) & 0x01) == 1,
                Ready = csLTDMC.LTDMC.dmc_check_done((ushort)cardNo, (ushort)(axisNo - 1)) == 1,
                ServoOn = Axis_StationMachine == 4,
            };
            return axisSts;
        }

        public StopType GetStopReason(short cardNo, short axisNo)
        {
            int reason = 0;
            short rtn = csLTDMC.LTDMC.dmc_get_stop_reason((ushort)cardNo, (ushort)(axisNo - 1), ref reason);
            switch (reason)
            {
                case 0:
                    return StopType.Normal;
                case 1:
                case 2:
                    return StopType.Alarm;
                case 4:
                    return StopType.Emg;
                case 5:
                case 6:
                case 7:
                case 8:
                    return StopType.HLimit;
                case 9:
                case 10:
                case 11:
                case 12:
                    return StopType.SLimit;
                case 13:
                case 14:
                    return StopType.Cmd;
                case 15:
                case 16:
                case 17:
                case 18:
                    return StopType.Other;
                case 19:
                    return StopType.IO;
            }
            return StopType.Other;
        }

        public void ResetServoWarn(short cardNo, short axisNo)
        {
            short rtn = csLTDMC.LTDMC.nmc_clear_axis_errcode((ushort)cardNo, (ushort)(axisNo - 1));
            CheckApiResult(rtn, $"清除轴伺服报警失败!");
        }

        public void SetAxisServoOff(short cardNo, short axisNo)
        {
            short rtn = csLTDMC. LTDMC.nmc_set_axis_disable((ushort)cardNo, (ushort)(axisNo - 1));// 使能对应轴

            CheckApiResult(rtn, "设置轴伺服Off失败!");
        }

        public void SetAxisServoOn(short cardNo, short axisNo)
        {
            short rtn = csLTDMC. LTDMC.nmc_set_axis_enable((ushort)cardNo, (ushort)(axisNo - 1));// 不使能对应轴

            CheckApiResult(rtn, "设置轴伺服ON失败!");
        }

        public void StopAxis(short cardNo, short axisNo, bool now)
        {
            short rtn = 0;
            if (!now)
            {
                rtn = csLTDMC.LTDMC.dmc_set_dec_stop_time((ushort)cardNo, (ushort)(axisNo - 1), 0.1);
                CheckApiResult(rtn, "设置减速停止减速度失败!");
            }
            CheckApiResult(csLTDMC.LTDMC.dmc_stop((ushort)cardNo, (ushort)(axisNo - 1), now ? (ushort)1 : (ushort)0), "停止轴运动失败!");
        }

        public double VelUnitConvert(double vel)
        {
            return vel;
        }

        public void ZeroAxisCommand(short cardNo, short axisNo)
        {
            
            CheckApiResult(csLTDMC.LTDMC.dmc_set_position_unit((ushort)cardNo, (ushort)(axisNo - 1), 0), "清除命令位置失败!");
        }

        public void ZeroAxisEncoder(short cardNo, short axisNo)
        {
            CheckApiResult(csLTDMC.LTDMC.dmc_set_encoder_unit((ushort)cardNo, (ushort)(axisNo - 1), 0), "清除编码器位置失败!");
        }

        public bool AxisChangeSpeed(short cardNo, short axisNo, AxisSpeed changedSpeed)
        {
            short rtn = csLTDMC.LTDMC.dmc_change_speed((ushort)cardNo, (ushort)(axisNo - 1), changedSpeed.Vel, changedSpeed.Acc);
            return CheckApiResult(rtn, "改变轴速度失败!");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="cardNo"></param>
        /// <param name="axisNo"></param>
        /// <param name="outPort"></param>
        /// <param name="logic">0-低电平有效，1-高电平</param>
        /// <param name="pulseWidth">1us~20s</param>
        public void ConfigureCompareOut(short cardNo, short axisNo, short outPort, short logic, int pulseWidth, List<int> comparePulse)
        {
            short rtn = csLTDMC.LTDMC.dmc_compare_clear_points((ushort)cardNo, (ushort)outPort);
            rtn += csLTDMC.LTDMC.dmc_compare_set_config((ushort)cardNo, (ushort)axisNo, 1, 1);
            for (int i = 0; i < comparePulse.Count; i++)
            {
                rtn += csLTDMC.LTDMC.dmc_compare_add_point_cycle_unit((ushort)cardNo, (ushort)axisNo, comparePulse[i], 1, (ushort)outPort, (uint)pulseWidth, (ushort)logic);
            }
            CheckApiResult(rtn, "配置比较输出失败!");
        }
    }

    public class HomeParam
    {
        public short AxisNo { get; set; }
        public bool IsHomeFinish { get; set; }
    }
}
